use rusqlite::{Connection, Result as SqliteResult, Transaction};
use std::sync::{Arc, Mutex};
use crate::error::AppError;

/// 事务管理器
pub struct TransactionManager {
    conn: Arc<Mutex<Connection>>,
}

impl TransactionManager {
    /// 创建新的事务管理器
    pub fn new(conn: Arc<Mutex<Connection>>) -> Self {
        Self { conn }
    }
    
    /// 执行事务
    pub fn transaction<F, T>(&self, f: F) -> Result<T, AppError>
    where
        F: FnOnce(&Transaction) -> Result<T, AppError>,
    {
        let mut conn = self.conn.lock().map_err(|e| {
            AppError::database(format!("Failed to acquire database lock: {}", e))
        })?;
        
        let tx = conn.transaction().map_err(|e| {
            AppError::database(format!("Failed to start transaction: {}", e))
        })?;
        
        match f(&tx) {
            Ok(result) => {
                tx.commit().map_err(|e| {
                    AppError::database(format!("Failed to commit transaction: {}", e))
                })?;
                Ok(result)
            }
            Err(e) => {
                // 回滚事务
                if let Err(rollback_err) = tx.rollback() {
                    log::error!("Failed to rollback transaction: {}", rollback_err);
                }
                Err(e)
            }
        }
    }
    
    /// 执行只读事务
    pub fn read_transaction<F, T>(&self, f: F) -> Result<T, AppError>
    where
        F: FnOnce(&Transaction) -> Result<T, AppError>,
    {
        let mut conn = self.conn.lock().map_err(|e| {
            AppError::database(format!("Failed to acquire database lock: {}", e))
        })?;
        
        let tx = conn.transaction().map_err(|e| {
            AppError::database(format!("Failed to start transaction: {}", e))
        })?;
        
        // 设置为只读事务
        tx.execute("PRAGMA query_only = ON", []).map_err(|e| {
            AppError::database(format!("Failed to set transaction to read-only: {}", e))
        })?;
        
        let result = f(&tx);
        
        // 无论成功与否都提交事务（只读事务不会修改数据）
        if let Err(commit_err) = tx.commit() {
            log::error!("Failed to commit read transaction: {}", commit_err);
        }
        
        result
    }
    
    /// 执行批量操作
    pub fn batch<F>(&self, f: F) -> Result<(), AppError>
    where
        F: FnOnce(&Transaction) -> Result<(), AppError>,
    {
        self.transaction(|tx| {
            // 开始批量操作
            tx.execute("BEGIN IMMEDIATE", []).map_err(|e| {
                AppError::database(format!("Failed to begin batch operation: {}", e))
            })?;
            
            f(tx)?;
            
            Ok(())
        })
    }
    
    /// 执行保存点事务
    pub fn savepoint<F, T>(&self, name: &str, f: F) -> Result<T, AppError>
    where
        F: FnOnce(&Transaction) -> Result<T, AppError>,
    {
        let mut conn = self.conn.lock().map_err(|e| {
            AppError::database(format!("Failed to acquire database lock: {}", e))
        })?;
        
        let tx = conn.transaction().map_err(|e| {
            AppError::database(format!("Failed to start transaction: {}", e))
        })?;
        
        // 创建保存点
        tx.execute(&format!("SAVEPOINT {}", name), []).map_err(|e| {
            AppError::database(format!("Failed to create savepoint: {}", e))
        })?;
        
        match f(&tx) {
            Ok(result) => {
                // 释放保存点
                tx.execute(&format!("RELEASE SAVEPOINT {}", name), []).map_err(|e| {
                    AppError::database(format!("Failed to release savepoint: {}", e))
                })?;
                
                tx.commit().map_err(|e| {
                    AppError::database(format!("Failed to commit transaction: {}", e))
                })?;
                
                Ok(result)
            }
            Err(e) => {
                // 回滚到保存点
                if let Err(rollback_err) = tx.execute(&format!("ROLLBACK TO SAVEPOINT {}", name), []) {
                    log::error!("Failed to rollback to savepoint: {}", rollback_err);
                }
                
                // 回滚整个事务
                if let Err(rollback_err) = tx.rollback() {
                    log::error!("Failed to rollback transaction: {}", rollback_err);
                }
                
                Err(e)
            }
        }
    }
}

/// 事务辅助函数
pub fn with_transaction<F, T>(conn: &mut Connection, f: F) -> SqliteResult<T>
where
    F: FnOnce(&Transaction) -> SqliteResult<T>,
{
    let tx = conn.transaction()?;
    match f(&tx) {
        Ok(result) => {
            tx.commit()?;
            Ok(result)
        }
        Err(e) => {
            tx.rollback()?;
            Err(e)
        }
    }
}

/// 只读事务辅助函数
pub fn with_read_transaction<F, T>(conn: &mut Connection, f: F) -> SqliteResult<T>
where
    F: FnOnce(&Transaction) -> SqliteResult<T>,
{
    let tx = conn.transaction()?;
    tx.execute("PRAGMA query_only = ON", [])?;
    let result = f(&tx);
    tx.commit()?;
    result
}

/// 批量操作辅助函数
pub fn with_batch<F>(conn: &mut Connection, f: F) -> SqliteResult<()>
where
    F: FnOnce(&Transaction) -> SqliteResult<()>,
{
    let tx = conn.transaction()?;
    tx.execute("BEGIN IMMEDIATE", [])?;
    match f(&tx) {
        Ok(_) => {
            tx.commit()?;
            Ok(())
        }
        Err(e) => {
            tx.rollback()?;
            Err(e)
        }
    }
}
